/*
 * Copyright 2008 Jens Meiss
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.hmvc4gwt.example.hmvcblog.frontend.dashboard.client.edit.blog;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.googlecode.hmvc4gwt.example.hmvcblog.frontend.client.applicationframe.events.in.AddApplicationViewEvent;
import com.googlecode.hmvc4gwt.example.hmvcblog.frontend.dashboard.client.edit.blog.events.in.ShowEditBlogViewEvent;
import com.googlecode.hmvc4gwt.example.hmvcblog.frontend.historytoken.client.HistoryToken;
import com.googlecode.hmvc4gwt.example.hmvcblog.frontend.i18n.client.I18N;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogEditDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogEditIdDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogUpdateDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.BlogEntryDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.BlogEntryRemoveDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.comment.BlogEntryCommentDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.gwtrpc.client.blog.BlogAsynCallback;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.gwtrpc.client.blog.entry.BlogEntryAsyncCallback;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.gwtrpc.client.blog.events.in.GetBlogEditDTOEvent;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.gwtrpc.client.blog.events.out.BlogNotFoundEvent;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.gwtrpc.client.blog.events.out.BlogSuccessfulUpdatedEvent;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.gwtrpc.client.blog.events.out.BlogTitleEmptyEvent;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.gwtrpc.client.blog.events.out.NotBlogOwnerEvent;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.gwtrpc.client.blog.events.out.ReceiveBlogEditDTOEvent;
import com.googlecode.hmvc4java.event.IEvent;
import com.googlecode.hmvc4java.registry.controller.AControllerModelViewRegistry;

/**
 * 
 * @author jens.meiss
 */
public class EditBlogController extends AControllerModelViewRegistry<EditBlogModel, EditBlogView> {

	private ClickListener clickListenerRemoveBlogEntry;
	
	private ClickListener clickListenerRemoveBlogEntryComment;

	private void addEntry() {
		
		History.newItem(HistoryToken.addBlogEntry + "=" + getModel().getBlogId());
		
	}

	/**
	 * @param blogEntryDTO
	 */
	private void createTreeItemBlogEntry(BlogEntryDTO blogEntryDTO, List<BlogEntryCommentDTO> listBlogEntryCommentDTO,Tree treeBlogEntries) {
		
		Label labelTitle = new Label(blogEntryDTO.getTitle());
		
		Hyperlink hyperlinkEdit = new Hyperlink(I18N.constants.linkEdit(), HistoryToken.editBlogEntry + "=" + blogEntryDTO.getId());
		Hyperlink hyperlinkRemove = new Hyperlink(I18N.constants.linkRemove(), "");
		hyperlinkRemove.addClickListener(getClickListenerRemoveBlogEntry());
		
		FlexTable tableBlogEntryTreeItem = new FlexTable();
		
		tableBlogEntryTreeItem.setWidget(0, 0, labelTitle);
		tableBlogEntryTreeItem.setWidget(0, 1, hyperlinkRemove);
		tableBlogEntryTreeItem.setWidget(0, 2, hyperlinkEdit);
		
		FlexCellFormatter cellFormatter = tableBlogEntryTreeItem.getFlexCellFormatter();
		cellFormatter.setColSpan(1, 0, 3);
		
		tableBlogEntryTreeItem.setWidget(1, 0, new Label(blogEntryDTO.getText()));
		
		TreeItem treeItemBlogEntry = treeBlogEntries.addItem(tableBlogEntryTreeItem);
		
		getModel().getMapTreeItemBlogEntryDTO().put(treeItemBlogEntry, blogEntryDTO);
		
		for (BlogEntryCommentDTO blogEntryCommentDTO : listBlogEntryCommentDTO) {
			
			createTreeItemBlogEntryComment(blogEntryCommentDTO, treeItemBlogEntry);
			
		}
	}

	/**
	 * @param blogEntryCommentDTO
	 * @param treeItemBlogEntry
	 */
	private void createTreeItemBlogEntryComment(
			BlogEntryCommentDTO blogEntryCommentDTO, TreeItem treeItemBlogEntry) {
		
		Label labelText = new Label(blogEntryCommentDTO.getText());
		
		Hyperlink hyperlinkRemove = new Hyperlink(I18N.constants.linkRemove(), "");
		hyperlinkRemove.addClickListener(getClickListenerRemoveBlogEntryComment());
		
		FlexTable flexTableBlogEntryComment = new FlexTable();
		
		flexTableBlogEntryComment.setWidget(0, 0, labelText);
		flexTableBlogEntryComment.setWidget(0, 1, hyperlinkRemove);
		
		TreeItem treeItemBlogComment = treeItemBlogEntry.addItem(flexTableBlogEntryComment);
		
		getModel().getMapTreeItemBlogEntryCommentDTO().put(treeItemBlogComment, blogEntryCommentDTO);
	}

	/**
	 * @return the clickListenerRemoveBlogEntry
	 */
	private ClickListener getClickListenerRemoveBlogEntry() {
		return clickListenerRemoveBlogEntry;
	}
	
	/**
	 * @return the clickListenerRemoveBlogEntryComment
	 */
	private ClickListener getClickListenerRemoveBlogEntryComment() {
		return clickListenerRemoveBlogEntryComment;
	}

	public void handleEvent(IEvent event) {
		
		if (event.getClass() == ShowEditBlogViewEvent.class) {
			
			showEditBlogView(((ShowEditBlogViewEvent) event).getBlogId());
			
		} else if (event.getClass() == BlogNotFoundEvent.class) {
			
			Window.alert(I18N.constants.messageBlogNotFound());
			History.newItem(HistoryToken.dashboard);
			getComponent().terminateComponent();
			
		} else if (event.getClass() == NotBlogOwnerEvent.class) {
			
			Window.alert(I18N.constants.messageBlogNotFound());
			getComponent().terminateComponent();
			
		} else if (event.getClass() == ReceiveBlogEditDTOEvent.class) {
			
			refreshView(((ReceiveBlogEditDTOEvent) event).getBlogEditDTO());
			
		} else if (event.getClass() == BlogSuccessfulUpdatedEvent.class) {
			
			History.newItem(HistoryToken.dashboard);
			
		} else if (event.getClass() == BlogTitleEmptyEvent.class) {
			
			showBlogTitleEmpty();
			
		}
		
	}
	
	public void init() {
		
		setClickListenerRemoveBlogEntry(new ClickListener() {
			public void onClick(Widget sender) {
				removeBlogEntry(getModel().getMapTreeItemBlogEntryDTO().get(getView().getTreeBlogEntries().getSelectedItem()));
			}
		});
		
		setClickListenerRemoveBlogEntryComment(new ClickListener() {
			public void onClick(Widget sender) {
				removeBlogEntryComment(getModel().getMapTreeItemBlogEntryCommentDTO().get(getView().getTreeBlogEntries().getSelectedItem()));
			}			
		});
		
		register(ShowEditBlogViewEvent.class);
		register(BlogNotFoundEvent.class);
		register(NotBlogOwnerEvent.class);
		register(ReceiveBlogEditDTOEvent.class);
		register(BlogSuccessfulUpdatedEvent.class);
		register(BlogTitleEmptyEvent.class);
		
		
	}
	
	public void initModel() {
		
		getModel().setMapTreeItemBlogEntryDTO(new HashMap<TreeItem, BlogEntryDTO>());
		getModel().setMapTreeItemBlogEntryCommentDTO(new HashMap<TreeItem, BlogEntryCommentDTO>());
		
	}
	
	public void initView() {
		
		Panel panelEditBlogView = new VerticalPanel();
		getView().setPanelEditBlogView(panelEditBlogView);
		
		Label labelTitle = new Label(I18N.constants.labelEditBlog());
		getView().setLabelTitle(labelTitle);
		
		HTMLTable tableBlogData = new Grid(3,3);
		getView().setTableBlogData(tableBlogData);
		
		TextBox textBoxTitle = new TextBox();
		getView().setTextBoxTitle(textBoxTitle);
		
		Label labelLastUpdate = new Label(I18N.constants.labelLastUpdate());
		getView().setLabelLastUpdated(labelLastUpdate);
		
		Label labelLastUpdateDate = new Label();
		getView().setLabelLastUpdatedDate(labelLastUpdateDate);
		
		Label labelDescription = new Label(I18N.constants.labelBlogDescription());
		getView().setLabelDescription(labelDescription);
		
		TextArea textAreaDescription = new TextArea();
		getView().setTextAreaDescription(textAreaDescription);
		
		Panel panelButtons = new HorizontalPanel();
		getView().setPanelButtons(panelButtons);
		
		Button buttonSave = new Button(I18N.constants.buttonSave());
		getView().setButtonSave(buttonSave);
		
		buttonSave.addClickListener(new ClickListener () {
			public void onClick(Widget sender) {
				save();
			}
		});
		
		Button buttonAddEntry = new Button(I18N.constants.buttonAddBlogEntry());
		getView().setButtonAddEntry(buttonAddEntry);
		
		buttonAddEntry.addClickListener(new ClickListener () {
			public void onClick(Widget sender) {
				addEntry();
			}			
		});
		
		Button buttonCancel = new Button(I18N.constants.buttonDashboard());
		getView().setButtonCancel(buttonCancel);
		
		buttonCancel.addClickListener(new ClickListener () {
			public void onClick(Widget sender) {
				History.newItem(HistoryToken.dashboard);
				getComponent().terminateComponent();
			}
		});
		
		Panel panelBlogDataAndButtons = new VerticalPanel();
		getView().setPanelBlogDataAndButtons(panelBlogDataAndButtons);
		
		Tree treeBlogEntries = new Tree();
		getView().setTreeBlogEntries(treeBlogEntries);
		
		/*
		 * build View
		 */		
		tableBlogData.setWidget(0, 0, labelTitle);		
		tableBlogData.setWidget(0, 1, textBoxTitle);
		tableBlogData.setWidget(1, 0, labelLastUpdate);
		tableBlogData.setWidget(1, 1, labelLastUpdateDate);
		tableBlogData.setWidget(2, 0, labelDescription);
		tableBlogData.setWidget(2, 1, textAreaDescription);
		
		panelButtons.add(buttonSave);
		panelButtons.add(buttonAddEntry);
		panelButtons.add(buttonCancel);
		
		panelBlogDataAndButtons.add(tableBlogData);
		panelBlogDataAndButtons.add(panelButtons);
		
		panelEditBlogView.add(labelTitle);
		panelEditBlogView.add(panelBlogDataAndButtons);
		panelEditBlogView.add(treeBlogEntries);
		
	}

	/**
	 * @param blogDTO
	 */
	private void refreshView(BlogEditDTO blogEditDTO) {				
		
		getView().getTextBoxTitle().setText(blogEditDTO.getTitle());
		getView().getTextAreaDescription().setText(blogEditDTO.getDescription());
		
		getView().getLabelLastUpdatedDate().setText(DateTimeFormat.getMediumDateTimeFormat().format(blogEditDTO.getDateLastUpdate()));
		
		showBlogEntries(blogEditDTO.getMapBlogEntryDTOListBlogEntryCommentDTO());
		
		fireEventGlobal(new AddApplicationViewEvent(null, getView().getWidget()));
		
	}
	
	private void removeBlogEntry(BlogEntryDTO blogEntryDTO) {
		
		if (Window.confirm(I18N.constants.messageConfirmRemoveBlogEntry())) {
			
			BlogEntryRemoveDTO blogEntryRemoveDTO = new BlogEntryRemoveDTO();
			blogEntryRemoveDTO.setId(blogEntryDTO.getId());
			
			BlogEntryAsyncCallback.remove(blogEntryRemoveDTO, this);
			
		}
		
	}

	private void removeBlogEntryComment(
			BlogEntryCommentDTO blogEntryCommentDTO) {
		
		if (Window.confirm(I18N.constants.messageConfirmRemoveBlogEntry())) {
			
			BlogEntryRemoveDTO blogEntryRemoveDTO = new BlogEntryRemoveDTO();
			blogEntryRemoveDTO.setId(blogEntryCommentDTO.getIdBlogEntryComment());
			
			BlogEntryAsyncCallback.remove(blogEntryRemoveDTO, this);
			
		}
		
	}

	private void save() {
		
		if (getView().getLabelBlogTitleEmpty() != null) {
			
			getView().getTableBlogData().remove(getView().getLabelBlogTitleEmpty());
			
		}
		
		BlogUpdateDTO blogUpdateDTO = new BlogUpdateDTO();
		blogUpdateDTO.setId(getModel().getBlogId());
		blogUpdateDTO.setTitle(getView().getTextBoxTitle().getText());
		blogUpdateDTO.setDescription(getView().getTextAreaDescription().getText());
		
		BlogAsynCallback.update(blogUpdateDTO, this);
	}

	/**
	 * @param clickListenerRemoveBlogEntry the clickListenerRemoveBlogEntry to set
	 */
	private void setClickListenerRemoveBlogEntry(
			ClickListener clickListenerRemoveBlogEntry) {
		this.clickListenerRemoveBlogEntry = clickListenerRemoveBlogEntry;
	}

	/**
	 * @param clickListenerRemoveBlogEntryComment the clickListenerRemoveBlogEntryComment to set
	 */
	private void setClickListenerRemoveBlogEntryComment(
			ClickListener clickListenerRemoveBlogEntryComment) {
		this.clickListenerRemoveBlogEntryComment = clickListenerRemoveBlogEntryComment;
	}

	/**
	 * @param mapBlogEntryDTOListBlogEntryCommentDTO
	 */
	private void showBlogEntries(
			Map<BlogEntryDTO, List<BlogEntryCommentDTO>> mapBlogEntryDTOListBlogEntryCommentDTO) {
		
		getView().getTreeBlogEntries().clear();
		
		for (BlogEntryDTO blogEntryDTO : mapBlogEntryDTOListBlogEntryCommentDTO.keySet()) {
		
			createTreeItemBlogEntry(blogEntryDTO, mapBlogEntryDTOListBlogEntryCommentDTO.get(blogEntryDTO), getView().getTreeBlogEntries());
			
		}
			
	}
	
	private void showBlogTitleEmpty() {
		
		if (getView().getLabelBlogTitleEmpty() == null) {
			
			Label labelBlogTitleEmpty = new Label(I18N.constants.labelBlogTitleEmpty());
			getView().setLabelBlogTitleEmpty(labelBlogTitleEmpty);
			
		}
		
		getView().getTableBlogData().setWidget(0, 2, getView().getLabelBlogTitleEmpty());
		
	}

	/**
	 * @param blogId
	 */
	private void showEditBlogView(int blogId) {
		
		getModel().setBlogId(blogId);
		
		BlogEditIdDTO blogEditIdDTO = new BlogEditIdDTO();
		blogEditIdDTO.setBlogId(blogId);
		
		fireEventGlobal(new GetBlogEditDTOEvent(blogEditIdDTO, this));
		
	}
	
	public void terminate() {
		History.newItem(HistoryToken.dashboard);
	}

}
